#include "tk_mem_pool.h"
#include <boost\pool\pool.hpp>

using namespace boost;

namespace tk
{
	enum MEM_BUF
	{
		MEM_4B = 4,
		MEM_8B = 8,
		MEM_16B = 16,
		MEM_32B = 32,
		MEM_64B = 64,
		MEM_128B = 128,
		MEM_256B = 256,
		MEM_512B = 512,
		MEM_1K = 1024,
		MEM_2K = 2048,
		MEM_4K = 4096,
		MEM_8K = 8192,
		MEM_16K = 16384,
		MEM_32K = 32768,
		MEM_64K = 65536,
		MEM_128K = 131072,
		MEM_256K = 262144,
		MEM_512K = 524288,
		MEM_1024K = 1048576,
		MEM_2048K = 2097152,
	};

tk_memory_pool::tk_memory_pool()
{
	m_p_lock = new TkMutex;

	m_p_pool_4b= new pool<> (MEM_4B);
	m_p_pool_8b= new pool<> (MEM_8B);
	m_p_pool_16b= new pool<> (MEM_16B);
	m_p_pool_32b= new pool<> (MEM_32B);
	m_p_pool_64b= new pool<> (MEM_64B);
	m_p_pool_128b= new pool<> (MEM_128B);
	m_p_pool_256b= new pool<> (MEM_256B);
	m_p_pool_512b= new pool<> (MEM_512B);
	m_p_pool_1k= new pool<> (MEM_1K);
	m_p_pool_2k= new pool<> (MEM_2K);
	m_p_pool_4k= new pool<> (MEM_4K);
	m_p_pool_8k= new pool<> (MEM_8K);
	m_p_pool_16k= new pool<> (MEM_16K);
	m_p_pool_32k= new pool<> (MEM_32K);
	m_p_pool_64k= new pool<> (MEM_64K);
	m_p_pool_128k= new pool<> (MEM_128K);
	m_p_pool_256k= new pool<> (MEM_256K);
	m_p_pool_512k= new pool<> (MEM_512K);
	m_p_pool_1024k= new pool<> (MEM_1024K);
}

tk_memory_pool::~tk_memory_pool()
{
	{
		TkMutexLocker lock(*m_p_lock);
		ReleaseAll();

		delete m_p_pool_4b;
		delete m_p_pool_8b;
		delete m_p_pool_16b;
		delete m_p_pool_32b;
		delete m_p_pool_64b;
		delete m_p_pool_128b;
		delete m_p_pool_256b;
		delete m_p_pool_512b;
		delete m_p_pool_1k;
		delete m_p_pool_2k;
		delete m_p_pool_4k;
		delete m_p_pool_8k;
		delete m_p_pool_16k;
		delete m_p_pool_32k;
		delete m_p_pool_64k;
		delete m_p_pool_128k;
		delete m_p_pool_256k;
		delete m_p_pool_512k;
		delete m_p_pool_1024k;
	}
	delete m_p_lock;
}

tk_pointer tk_memory_pool::Malloc(tk_int32 malloc_size)
{
	Q_ASSERT(malloc_size>0);
	TkMutexLocker lock(*m_p_lock);

	tk_pointer p = NULL;
	if (malloc_size == 0)
	{
		return p;
	}
#define TEMP_DEFINE(pl,size) \
	else if(malloc_size<=size)\
	{\
		p = ((pool<> *)pl)->malloc();\
		assert(p);\
		assert(((pool<> *)pl)->is_from(p));\
		return p;\
	}

	TEMP_DEFINE(m_p_pool_4b,MEM_4B)
	TEMP_DEFINE(m_p_pool_8b,MEM_8B)
	TEMP_DEFINE(m_p_pool_16b,MEM_16B)
	TEMP_DEFINE(m_p_pool_32b,MEM_32B)
	TEMP_DEFINE(m_p_pool_64b,MEM_64B)
	TEMP_DEFINE(m_p_pool_128b,MEM_128B)
	TEMP_DEFINE(m_p_pool_256b,MEM_256B)
	TEMP_DEFINE(m_p_pool_512b,MEM_512B)
	TEMP_DEFINE(m_p_pool_1k,MEM_1K)
	TEMP_DEFINE(m_p_pool_2k,MEM_2K)
	TEMP_DEFINE(m_p_pool_4k,MEM_4K)
	TEMP_DEFINE(m_p_pool_8k,MEM_8K)
	TEMP_DEFINE(m_p_pool_16k,MEM_16K)
	TEMP_DEFINE(m_p_pool_32k,MEM_32K)
	TEMP_DEFINE(m_p_pool_64k,MEM_64K)
	TEMP_DEFINE(m_p_pool_128k,MEM_128K)
	TEMP_DEFINE(m_p_pool_256k,MEM_256K)
	TEMP_DEFINE(m_p_pool_512k,MEM_512K)
	TEMP_DEFINE(m_p_pool_1024k,MEM_1024K)

#undef TEMP_DEFINE

	else// if (malloc_size>MEM_2048K)
	{
		p = new tk_char [malloc_size];
		return p;
	}
}

void tk_memory_pool::Free(tk_pointer p_mem,tk_int32 malloc_size)
{
	Q_ASSERT(p_mem && malloc_size>0);
	
	TkMutexLocker lock(*m_p_lock);

	if (p_mem == TK_NULL_PTR || malloc_size == 0)
	{
		return;
	}

#define TEMP_DEFINE(pl,size) \
	else if(malloc_size<=size)\
	{\
		assert(((pool<> *)pl)->is_from(p_mem));\
		((pool<> *)pl)->free(p_mem);\
		return;\
	}
	
	TEMP_DEFINE(m_p_pool_4b,MEM_4B)
	TEMP_DEFINE(m_p_pool_8b,MEM_8B)
	TEMP_DEFINE(m_p_pool_16b,MEM_16B)
	TEMP_DEFINE(m_p_pool_32b,MEM_32B)
	TEMP_DEFINE(m_p_pool_64b,MEM_64B)
	TEMP_DEFINE(m_p_pool_128b,MEM_128B)
	TEMP_DEFINE(m_p_pool_256b,MEM_256B)
	TEMP_DEFINE(m_p_pool_512b,MEM_512B)
	TEMP_DEFINE(m_p_pool_1k,MEM_1K)
	TEMP_DEFINE(m_p_pool_2k,MEM_2K)
	TEMP_DEFINE(m_p_pool_4k,MEM_4K)
	TEMP_DEFINE(m_p_pool_8k,MEM_8K)
	TEMP_DEFINE(m_p_pool_16k,MEM_16K)
	TEMP_DEFINE(m_p_pool_32k,MEM_32K)
	TEMP_DEFINE(m_p_pool_64k,MEM_64K)
	TEMP_DEFINE(m_p_pool_128k,MEM_128K)
	TEMP_DEFINE(m_p_pool_256k,MEM_256K)
	TEMP_DEFINE(m_p_pool_512k,MEM_512K)
	TEMP_DEFINE(m_p_pool_1024k,MEM_1024K)

#undef TEMP_DEFINE
	else// if (malloc_size>MEM_2048K)
	{
		delete [] p_mem;
	}
	return;
}

void tk_memory_pool::ReleaseAll()
{
	TkMutexLocker lock(*m_p_lock);

	((pool<> *)m_p_pool_4b)->purge_memory();
	((pool<> *)m_p_pool_8b)->purge_memory();
	((pool<> *)m_p_pool_16b)->purge_memory();
	((pool<> *)m_p_pool_32b)->purge_memory();
	((pool<> *)m_p_pool_64b)->purge_memory();
	((pool<> *)m_p_pool_128b)->purge_memory();
	((pool<> *)m_p_pool_256b)->purge_memory();
	((pool<> *)m_p_pool_512b)->purge_memory();
	((pool<> *)m_p_pool_1k)->purge_memory();
	((pool<> *)m_p_pool_2k)->purge_memory();
	((pool<> *)m_p_pool_4k)->purge_memory();
	((pool<> *)m_p_pool_8k)->purge_memory();
	((pool<> *)m_p_pool_16k)->purge_memory();
	((pool<> *)m_p_pool_32k)->purge_memory();
	((pool<> *)m_p_pool_64k)->purge_memory();
	((pool<> *)m_p_pool_128k)->purge_memory();
	((pool<> *)m_p_pool_256k)->purge_memory();
	((pool<> *)m_p_pool_512k)->purge_memory();
	((pool<> *)m_p_pool_1024k)->purge_memory();
}


tk_memory_pool g_gobal_pool;


}
